home *** CD-ROM | disk | FTP | other *** search
- { *****************************************************
- TCalendarLabel Component
-
- The TRngSelCalendar component is an improved version of the
- calendar provided on the Samples page of Delphi 1.02.
- Improvements include the ability to store strings in
- the cells, provide foreground color for occupied cells
- and drag/drop abilities.
-
- The TCalendarLabel component attaches to a TRngSelCalendar and
- displays the month and year. TCalLabel responds to the
- HookEvent event. See unit EList.pas for details.
-
- Paul Warren
- HomeGrown Software Development
- (c) 1997 Langley British Columbia.
- (604) 856-6523
- e-mail: hg_soft@uniserve.com
- Home page: http://users.uniserve.com/~hg_soft
- ***************************************************** }
-
- unit Enhcalnd;
-
- interface
-
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- Wintypes, WinProcs,
- {$ENDIF}
- Classes, Controls, Messages, Forms, Graphics, StdCtrls,
- Grids, SysUtils, Menus, ExtCtrls, EList;
-
- type
- TDayOfWeek = 0..6;
-
- TMonthChange = procedure(Sender: TObject; Month: Integer) of object;
- TYearChange = procedure(Sender: TObject; Year: Integer) of object;
- TDateChange = procedure(Sender: TObject; NewDate: TDateTime) of object;
- TDroppedCell = procedure(Sender: TObject; ACol, ARow: LongInt;
- var Value: string) of object;
- TCellDragOver = procedure(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean) of object;
-
- TBaseCalendar = class(TCustomGrid)
- private
- { Private declarations }
- FBlockWeekends: Boolean;
- FBlockedColor: TColor;
- FDate: TDateTime;
- FFixedHeader: Boolean;
- FMonthOffset: Integer;
- FReadOnly: Boolean;
- FStartOfWeek: TDayOfWeek;
- FUpdating: Boolean;
- FMonthChange: TMonthChange;
- FYearChange: TYearChange;
- FDateChange: TDateChange;
- FEventList: TEventList;
- FHookEvent: TNotifyEvent;
- function GetCellText(ACol, ARow: Integer): string;
- function GetDateElement(Index: Integer): Integer;
- procedure SetBlockWeekends(Value: Boolean);
- procedure SetBlockedColor(Value: TColor);
- procedure SetCalendarDate(Value: TDateTime);
- procedure SetDateElement(Index: Integer; Value: Integer);
- procedure SetFixedHeader(Value: Boolean);
- procedure SetStartOfWeek(Value: TDayOfWeek);
- procedure SetHookEvent(Value: TNotifyEvent);
- protected
- { Protected declarations }
- procedure Loaded; override;
- procedure Click; override;
- procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
- function DaysPerMonth(AYear, AMonth: Integer): Integer; virtual;
- function IsLeapYear(AYear: Integer): Boolean; virtual;
- function SelectCell(ACol, ARow: Longint): Boolean; override;
- public
- { Public declarations }
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
- procedure NextMonth;
- procedure NextYear;
- procedure PrevMonth;
- procedure PrevYear;
- function DaysThisMonth: Integer;
- function IsWeekend(ADay: integer): boolean;
- procedure UpdateCalendar; virtual;
- function GetComponentImage: TBitmap;
- procedure MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
- property CellText[ACol, ARow: Integer]: string read GetCellText;
- property CalendarDate: TDateTime read FDate write SetCalendarDate stored false;
- property Day: Integer index 3 read GetDateElement write SetDateElement stored false;
- property Month: Integer index 2 read GetDateElement write SetDateElement stored false;
- property Year: Integer index 1 read GetDateElement write SetDateElement stored false;
- property BlockWeekends: Boolean read FBlockWeekends write SetBlockWeekends default false;
- property BlockedColor: TColor read FBlockedColor write SetBlockedColor default clGray;
- property FixedHeader: Boolean read FFixedHeader write SetFixedHeader default True;
- property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
- property StartOfWeek: TDayOfWeek read FStartOfWeek write SetStartOfWeek;
- property OnDateChange: TDateChange read FDateChange write FDateChange;
- property OnMonthChange: TMonthChange read FMonthChange write FMonthChange;
- property OnYearChange: TYearChange read FYearChange write FYearChange;
- property HookEvent: TNotifyEvent write SetHookEvent;
- published
- { Published declarations }
- end;
-
- TCalendarStrings = array[0..6, 0..6] of TStringList;
- TNeedStrings = procedure(Sender: TObject; ACol, ARow: LongInt;
- ADate: TDateTime; var Value: TStringList) of object;
-
- TStringsCalendar = class(TBaseCalendar)
- private
- { Private declarations }
- FCalStrings: TCalendarStrings;
- FOnDroppedCell: TDroppedCell;
- FOnCellDragOver: TCellDragOver;
- FOnNeedStrings: TNeedStrings;
- function GetCalStrings(ACol, ARow: integer): TStringList; virtual;
- procedure SetCalStrings(ACol, ARow: Integer; Value: TStringList); virtual;
- procedure SetCellString(ACol, ARow, ADay: Integer; Value: string); virtual;
- protected
- { Protected declarations }
- procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
- procedure AcceptDropped(Sender, Source: TObject; X, Y: integer);
- procedure CellDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- public
- { Public declarations }
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure ClearAllDays;
- property CellString[ACol, ARow, ADay: Integer]: string write SetCellString;
- property CalStrings[ACol, ARow: Integer]: TStringList read GetCalStrings write SetCalStrings;
- published
- { Published declarations }
- property OnDroppedCell: TDroppedCell read FOnDroppedCell write FOnDroppedCell;
- property OnCellDragOver: TCellDragOver read FOnCellDragOver write FOnCellDragOver;
- property OnNeedStrings: TNeedStrings read FOnNeedStrings write FOnNeedStrings;
- property BlockWeekends;
- property BlockedColor;
- property FixedHeader;
- property ReadOnly;
- property StartOfWeek;
- property OnDateChange;
- property OnMonthChange;
- property OnYearChange;
- property Align;
- property BorderStyle;
- property Color;
- property Ctl3D;
- property DragCursor;
- property DragMode;
- property Enabled;
- property FixedColor;
- property Font;
- property ParentColor;
- property ParentCtl3D;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property TabOrder;
- property TabStop;
- property Visible;
- property OnClick;
- property OnDblClick;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnKeyDown;
- property OnKeyPress;
- property OnKeyUp;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- end;
-
- TRngSelCalendar = class(TStringsCalendar)
- private
- { private declarations }
- FRangeColor: TColor;
- FStartDate: TDateTime;
- FEndDate: TDateTime;
- FOnRngSelect: TNotifyEvent;
- procedure SetStartDate(Value: TDateTime);
- procedure SetEndDate(Value: TDateTime);
- protected
- { protected declarations }
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
- public
- { public declarations }
- constructor Create(AOwner: TComponent); override;
- property StartDate: TDateTime read FStartDate write SetStartDate;
- property EndDate: TDateTime read FEndDate write SetEndDate;
- published
- { published declarations }
- property RangeColor: TColor read FRangeColor write FRangeColor default clBlue;
- property OnRngSelect: TNotifyEvent read FOnRngSelect write FOnRngSelect;
- end;
- TCalendarLabel = class(TLabel) private
- { private declarations }
- FCalendarSource: TStringsCalendar;
- procedure SetSource(Value: TStringsCalendar);
- protected
- { protected declarations }
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure DateChange(Sender: TObject);
- public
- { public declarations }
- procedure Loaded; override;
- procedure UpdateLabel;
- published
- { published declarations }
- property CalendarSource: TStringsCalendar read FCalendarSource write SetSource;
- end;
-
- implementation
-
- {$IFDEF WIN32}
- {$R ENHCALND.D32}
- {$ELSE}
- {$R ENHCALND.D16}
- {$ENDIF}
-
- { TBaseCalendar }
- constructor TBaseCalendar.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- { defaults }
- ColCount := 7;
- FixedCols := 0;
- FixedRows := 1;
- Options := Options - [goRangeSelect] + [goDrawFocusSelected];
- RowCount := 7;
- ScrollBars := ssNone;
- FBlockWeekends := false;
- FBlockedColor := clGray;
- FDate := Date;
- FFixedHeader := true;
- FEventList := TEventList.Create;
- end;
-
- destructor TBaseCalendar.Destroy;
- begin
- FEventList.Free;
- inherited Destroy;
- end;
-
- { Loaded override }
- procedure TBaseCalendar.Loaded;
- begin
- inherited Loaded;
- UpdateCalendar;
- end;
-
- { Click override - sets day to the cell clicked }
- procedure TBaseCalendar.Click;
- var
- TheCellText: string;
- begin
- TheCellText := CellText[Col, Row];
- if TheCellText <> '' then Day := StrToInt(TheCellText);
- inherited Click;
- end;
-
- { IsLeapYear - support routine }
- function TBaseCalendar.IsLeapYear(AYear: Integer): Boolean;
- begin
- Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0));
- end;
-
- { DaysPerMonth - protected implementation of DaysThisMonth }
- function TBaseCalendar.DaysPerMonth(AYear, AMonth: Integer): Integer;
- const
- DaysInMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
- begin
- Result := DaysInMonth[AMonth];
- if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special }
- end;
-
- { DaysThisMonth - support routine to return the days in the current month }
- function TBaseCalendar.DaysThisMonth: Integer;
- begin
- Result := DaysPerMonth(Year, Month);
- end;
-
- { IsWeekend - support routine to determine if a given day is a weekend }
- function TBaseCalendar.IsWeekend(ADay: integer): boolean;
- var
- i, j: integer;
- TheCellText: string;
- begin
- Result := false;
- for i := 0 to 6 do
- for j := 1 to 6 do
- begin
- TheCellText := CellText[i, j];
- if (TheCellText <> '') and (ADay = StrToInt(TheCellText)) then
- if (i = 0) or (i = 6) then
- Result := true
- else Result := false;
- end;
- end;
-
- { MouseToCell - support routine to convert the mouse position
- to cell coords }
- procedure TBaseCalendar.MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
- var
- Coord: TGridCoord;
- begin
- Coord := MouseCoord(X, Y);
- ACol := Coord.X;
- ARow := Coord.Y;
- end;
-
- { DrawCell override }
- procedure TBaseCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
- var
- TheText: string;
- begin
- TheText := CellText[ACol, ARow];
- if ((ACol = 0) or (ACol = 6)) and FBlockWeekends and (TheText <> '') and (ARow <> 0) then
- Canvas.Brush.Color := BlockedColor;
- with ARect, Canvas do
- TextRect(ARect, (Left + 1), (Top + 1), TheText);
- end;
-
- { GetCellText - property access method to return the selected date
- as a string. Acts as a storage device for the dates }
- function TBaseCalendar.GetCellText(ACol, ARow: Integer): string;
- var
- DayNum: Integer;
- begin
- if ARow = 0 then { day names at tops of columns }
- Result := ShortDayNames[(StartOfWeek + ACol) mod 7 + 1]
- else
- begin
- DayNum := FMonthOffset + ACol + (ARow - 1) * 7;
- if (DayNum < 1) or (DayNum > DaysThisMonth) then Result := ''
- else Result := IntToStr(DayNum);
- end;
- end;
-
- { SelectCell override - returns false for cells that shouldn't be
- selected }
- function TBaseCalendar.SelectCell(ACol, ARow: Longint): Boolean;
- begin
- Result := inherited SelectCell(ACol, ARow);
- if ((not FUpdating) and FReadOnly) or (CellText[ACol, ARow] = '') then
- Result := False;
- if FBlockWeekends and ((ACol = 0) or (ACol = 6)) then
- Result := False;
- end;
-
- { SetCalendarDate - property access method to set calendar focused date }
- procedure TBaseCalendar.SetCalendarDate(Value: TDateTime);
- begin
- if Value <> FDate then
- begin
- FDate := Value;
- UpdateCalendar;
- end;
- end;
-
- { SetDateElement - internal method to get day, month or year }
- function TBaseCalendar.GetDateElement(Index: Integer): Integer;
- var
- AYear, AMonth, ADay: Word;
- begin
- DecodeDate(FDate, AYear, AMonth, ADay);
- case Index of
- 1: Result := AYear;
- 2: Result := AMonth;
- 3: Result := ADay;
- else Result := -1;
- end;
- end;
-
- { SetDateElement - internal method to set day, month or year }
- procedure TBaseCalendar.SetDateElement(Index: Integer; Value: Integer);
- var
- AYear, AMonth, ADay: Word;
- begin
- if Value > 0 then
- begin
- DecodeDate(FDate, AYear, AMonth, ADay);
- case Index of
- 1: if AYear <> Value then AYear := Value else Exit;
- 2: if (Value <= 12) and (Value <> AMonth) then AMonth := Value else Exit;
- 3: if (Value <= DaysThisMonth) and (Value <> ADay) then ADay := Value else Exit;
- else Exit;
- end;
- if ADay > DaysPerMonth(AYear, AMonth) then ADay := DaysPerMonth(AYear, AMonth);
- FDate := EncodeDate(AYear, AMonth, ADay);
- UpdateCalendar;
- end;
- end;
-
- { SetHookEvent - property access method to attach a HookEvent }
- procedure TBaseCalendar.SetHookEvent(Value: TNotifyEvent);
- begin
- FEventList.AddEvent(Value);
- end;
-
- { SetStartOfWeek - property access method to change the starting
- day of the week. }
- procedure TBaseCalendar.SetStartOfWeek(Value: TDayOfWeek);
- begin
- if Value <> FStartOfWeek then
- begin
- FStartOfWeek := Value;
- UpdateCalendar;
- end;
- end;
-
- { SetFixedHeader - property access method to toggle fixed header }
- procedure TBaseCalendar.SetFixedHeader(Value: Boolean);
- begin
- FFixedHeader := Value;
- SetBounds(Left, Top, Width, Height);
- end;
-
- { SetBlockWeekends - property access method to toggle
- weekend blocking. }
- procedure TBaseCalendar.SetBlockWeekends(Value: Boolean);
- begin
- if Value <> FBlockWeekends then
- begin
- FBlockWeekends := Value;
- Invalidate;
- end;
- end;
-
- { SetBlockedColor - property access method to set the color for
- blocked days. clSilver doesn't look good. }
- procedure TBaseCalendar.SetBlockedColor(Value: TColor);
- begin
- if Value <> FBlockedColor then
- begin
- FBlockedColor := Value;
- Invalidate;
- end;
- end;
-
- { PrevMonth }
- procedure TBaseCalendar.PrevMonth;
- begin
- if Month > 1 then Month := pred(Month)
- else begin
- Year := Year - 1;
- Month := 12;
- end;
- if Assigned(FMonthChange) then FMonthChange(Self, Month);
- end;
-
- { NextMonth }
- procedure TBaseCalendar.NextMonth;
- begin
- if Month < 12 then Month := succ(Month)
- else begin
- Year := Year + 1;
- Month := 1;
- end;
- if Assigned(FMonthChange) then FMonthChange(Self, Month);
- end;
-
- { NextYear }
- procedure TBaseCalendar.NextYear;
- begin
- if IsLeapYear(Year) and (Month = 2) and (Day = 29) then Day := 28;
- Year := Year + 1;
- if Assigned(FYearChange) then FYearChange(Self, Year);
- end;
-
- { PrevYear }
- procedure TBaseCalendar.PrevYear;
- begin
- if IsLeapYear(Year) and (Month = 2) and (Day = 29) then Day := 28;
- Year := Year - 1;
- if Assigned(FYearChange) then FYearChange(Self, Year);
- end;
-
- { UpdateCalendar - central "engine" }
- procedure TBaseCalendar.UpdateCalendar;
- var
- AYear, AMonth, ADay: Word;
- FirstDate: TDateTime;
- i: integer;
- begin
- FUpdating := True;
- try
- DecodeDate(FDate, AYear, AMonth, ADay);
- FirstDate := EncodeDate(AYear, AMonth, 1);
- { day of week for 1st of month }
- FMonthOffset := 2 - ((DayOfWeek(FirstDate) - FStartOfWeek + 7) mod 7);
- if FMonthOffset = 2 then FMonthOffset := -5;
- MoveColRow((ADay - FMonthOffset) mod 7, (ADay - FMonthOffset) div 7 + 1,
- False, False);
- Invalidate;
- { trigger OnDateChange and all HookEvents }
- if Assigned(FDateChange) then FDateChange(Self, FDate);
- for i := 0 to FEventList.Count-1 do
- begin
- FHookEvent := FEventList.Events[i];
- FHookEvent(Self);
- end;
- finally
- FUpdating := False;
- end;
- end;
-
- procedure TBaseCalendar.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
- var
- FixedSize: integer;
- GridLines: Integer;
- begin
- GridLines := 6 * GridLineWidth;
- { set size of title row }
- FixedSize := Font.Size + 8;
- DefaultColWidth := (AWidth - GridLines) div 7;
- if FFixedHeader then
- begin
- DefaultRowHeight := ((AHeight - FixedSize) - GridLines) div 6;
- {$IFDEF WIN32}
- AHeight := (((DefaultRowHeight + GridLineWidth) * 6) + 4 + (FixedSize + GridLineWidth));
- {$ELSE}
- AHeight := (((DefaultRowHeight + GridLineWidth) * 6) + 2 + (FixedSize + GridLineWidth));
- {$ENDIF}
- RowHeights[0] := FixedSize;
- end else begin
- DefaultRowHeight := (AHeight - GridLines) div 7;
- {$IFDEF WIN32}
- AHeight := (((DefaultRowHeight + GridLineWidth) * 7) + 4);
- {$ELSE}
- AHeight := (((DefaultRowHeight + GridLineWidth) * 7) + 2);
- {$ENDIF}
- end;
- {$IFDEF WIN32}
- AWidth := (((DefaultColWidth + GridLineWidth) * 7) + 4);
- {$ELSE}
- AWidth := (((DefaultColWidth + GridLineWidth) * 7) + 2);
- {$ENDIF}
- inherited SetBounds(ALeft, ATop, AWidth, AHeight);
- end;
-
- { GetComponentImage - method to turn on-screen rendering into a bitmap.
- Allows easy printing }
- {$IFDEF WIN32}
- function TBaseCalendar.GetComponentImage: TBitmap;
- begin
- Result := TBitmap.Create;
- try
- Result.Width := ClientWidth+1;
- Result.Height := ClientHeight+1;
- Result.Canvas.Brush := Brush;
- Result.Canvas.FillRect(ClientRect);
- Result.Canvas.Lock;
- try
- PaintTo(Result.Canvas.Handle, -1, -1);
- finally
- Result.Canvas.Unlock;
- end;
- except
- Result.Free;
- raise;
- end;
- end;
- {$ELSE}
- function TBaseCalendar.GetComponentImage: TBitmap;
- var
- ScreenDC, PrintDC: HDC;
- OldBits, PrintBits: HBITMAP;
- PaintLParam: Longint;
-
- procedure PrintHandle(Handle: HWND);
- var
- R: TRect;
- SavedIndex: Integer;
- begin
- SavedIndex := SaveDC(PrintDC);
- WinProcs.GetClientRect(Handle, R);
- MapWindowPoints(Handle, Self.Handle, R, 2);
- with R do
- begin
- SetWindowOrgEx(PrintDC, -Left, -Top, nil);
- IntersectClipRect(PrintDC, 0, 0, Right - Left, Bottom - Top);
- end;
- SendMessage(Handle, WM_ERASEBKGND, PrintDC, 0);
- SendMessage(Handle, WM_PAINT, PrintDC, PaintLParam);
- RestoreDC(PrintDC, SavedIndex);
- end;
-
- begin
- Result := nil;
- ScreenDC := GetDC(0);
- PaintLParam := 0;
- try
- PrintDC := CreateCompatibleDC(ScreenDC);
- { Work around an apparent bug in Windows NT }
- if GetWinFlags and $4000 <> 0 then PaintLParam := PrintDC or $DEFE0000;
- try
- PrintBits := CreateCompatibleBitmap(ScreenDC, ClientWidth, ClientHeight);
- try
- OldBits := SelectObject(PrintDC, PrintBits);
- try
- { Clear the contents of the bitmap }
- FillRect(PrintDC, ClientRect, Brush.Handle);
-
- { Paint form into a bitmap }
- PrintHandle(Handle);
- finally
- SelectObject(PrintDC, OldBits);
- end;
- Result := TBitmap.Create;
- Result.Handle := PrintBits;
- PrintBits := 0;
- except
- Result.Free;
- if PrintBits <> 0 then DeleteObject(PrintBits);
- raise;
- end;
- finally
- DeleteDC(PrintDC);
- end;
- finally
- ReleaseDC(0, ScreenDC);
- end;
- end;
- {$ENDIF}
-
- { TStringsCalendar }
- constructor TStringsCalendar.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- { clear cells - reason: explicitly set to nil
- to avoid problems later }
- ClearAllDays;
- { set drag methods }
- OnDragDrop := AcceptDropped;
- OnDragOver := CellDragOver;
- end;
-
- destructor TStringsCalendar.Destroy;
- begin
- { clear cells }
- ClearAllDays;
- inherited Destroy;
- end;
-
- { ClearAllDays - method to clear cells }
- procedure TStringsCalendar.ClearAllDays;
- var
- i, j: integer;
- begin
- {iterate through array and free all StringLists }
- for i := 0 to 6 do
- for j := 0 to 6 do
- begin
- FCalStrings[i, j].Free;
- { explicitly set to nil or else... }
- FCalStrings[i, j] := nil;
- end;
- UpdateCalendar;
- end;
-
- { AcceptDropped override }
- procedure TStringsCalendar.AcceptDropped(Sender, Source: TObject; X, Y: integer);
- var
- ACol, ARow: LongInt;
- Value: string;
- begin
- { convert X and Y to Col and Row for convenience }
- MouseToCell(X, Y, ACol, ARow);
- { let user respond to event }
- if Assigned(FOnDroppedCell) then FOnDroppedCell(Source, ACol, ARow, Value);
- { if user returns a string add it to the cells list }
- if Value <> '' then SetCellString(ACol, ARow, 0, Value);
- { set focus to calendar }
- SetFocus;
- { force redraw }
- Invalidate;
- end;
-
- { CellDragOver override }
- procedure TStringsCalendar.CellDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- var
- ACol, ARow: LongInt;
- begin
- { convert X and Y to Col and Row for convenience }
- MouseToCell(X, Y, ACol, ARow);
- { allow user to set Accept the way they want }
- if Assigned(FOnCellDragOver) then FOnCellDragOver(Sender, Source, ACol, ARow, State, Accept);
- { if Accept = true then apply further logic else leave Accept = false }
- if Accept = true then
- if (not FUpdating) and (not FReadOnly) and (CellText[ACol, ARow] <> '') then
- Accept := true
- else Accept := false;
- end;
-
- { DrawCell }
- procedure TStringsCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
- var
- Temp: TStringList;
- i: integer;
- StrRect: TRect;
- ADate: TDateTime;
- AStrings: TStringList;
- begin
- { don't try to draw strings if they're in row 0 }
- if (ARow <> 0) then
- begin
- if (CellText[ACol, ARow] <> '') then
- begin
- { accept any strings assigned in the OnNeedStrings event }
- ADate := EncodeDate(Year, Month, StrToInt(CellText[ACol, ARow]));
- AStrings := FCalStrings[ACol, ARow];
- if Assigned(FOnNeedStrings) then FOnNeedStrings(Self, ACol, ARow, ADate, AStrings);
- if AStrings <> nil then FCalStrings[ACol, ARow] := AStrings;
- end;
- { color occupied cells }
- if (FCalStrings[ACol, ARow] <> nil) and not (gdFocused in AState) then
- Canvas.Brush.Color := clYellow;
- inherited DrawCell(ACol, ARow, ARect, AState);
- { don't try to draw strings if they're nil }
- if FCalStrings[ACol, ARow] <> nil then
- begin
- Temp := FCalStrings[ACol, ARow];
- for i := 0 to Temp.Count-1 do
- begin
- { set the clipping Rect }
- StrRect := Rect(ARect.Left,ARect.Top+((i+1)*Canvas.TextHeight('Test')),
- ARect.Right, ARect.Bottom);
- { if there is room draw the lines }
- if StrRect.Bottom-StrRect.Top >= Canvas.TextHeight('Test') then
- Canvas.TextRect(StrRect, StrRect.Left + 1, StrRect.Top + 1, Temp.Strings[i]);
- end;
- end;
- end else inherited DrawCell(ACol, ARow, ARect, AState);
- end;
-
- { SetCellString - adds a string to the cells stringlist based on Col
- or Row or Day of month. }
- procedure TStringsCalendar.SetCellString(ACol, ARow, ADay: Integer; Value: string);
- var
- i, j: integer;
- TheCellText: string;
- begin
- if (not FUpdating) and (not FReadOnly) and (CellText[ACol, ARow] <> '') then
- begin
- { if ADay is being used calc ACol and ARow. Doesn't matter if
- ACol and ARow are <> 0 we just calc them anyway }
- if ADay <> 0 then
- begin
- for i := 0 to 6 do
- for j := 1 to 6 do
- begin
- TheCellText := CellText[i, j];
- if (TheCellText <> '') and (ADay = StrToInt(TheCellText)) then
- begin
- ACol := i;
- ARow := j;
- end;
- end;
- end;
- { if no StringList assigned then create one }
- if FCalStrings[ACol, ARow] = nil then
- FCalStrings[ACol, ARow] := TStringList.Create;
- { add the line of text }
- FCalStrings[ACol, ARow].Add(Value);
- end;
- end;
-
- procedure TStringsCalendar.SetCalStrings(ACol, ARow: integer; Value: TStringList);
- begin FCalStrings[ACol, ARow] := Value;end;{ GetCalStrings - allows access to cells stringlist object. Useful
- for working with TList and TMemo }
- function TStringsCalendar.GetCalStrings(ACol, ARow: integer): TStringList;
- begin
- { method to return StringList as an object }
- Result := FCalStrings[ACol, ARow];
- end;
- { TRngSelCalendar }constructor TRngSelCalendar.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- { defaults }
- FRangeColor := clBlue;
- FStartDate := FDate;
- FEndDate := FDate;
- end;
-
- procedure TRngSelCalendar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- inherited MouseUp(Button, Shift, X, Y);
- if Button = mbLeft then
- begin
- if not (ssShift in Shift) then
- begin
- FStartDate := FDate;
- FEndDate := FDate;
- end else FEndDate := FDate;
- end;
- if Assigned(FOnRngSelect) then FOnRngSelect(Self);
- end;
- procedure TRngSelCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);var
- AYear, AMonth, ADay: Word;
- TmpDate: TDateTime;
- TheText: string;
- begin
- TheText := CellText[ACol, ARow];
- if (TheText <> '') and (ARow <> 0) then
- begin
- DecodeDate(FDate, AYear, AMonth, ADay);
- TmpDate := EncodeDate(AYear, AMonth, StrToInt(TheText));
- if (TmpDate >= FStartDate) and (TmpDate <= FEndDate)
- and (FStartDate <> FEndDate) then
- Canvas.Brush.Color := FRangeColor;
- end;
- inherited DrawCell(ACol, ARow, ARect, AState);
- end;
- procedure TRngSelCalendar.SetStartDate(Value: TDateTime);begin
- if Value <> FStartDate then
- begin
- FStartDate := Value;
- UpdateCalendar;
- end;
- end;
-
- procedure TRngSelCalendar.SetEndDate(Value: TDateTime);
- begin
- if Value <> FEndDate then
- begin
- FEndDate := Value;
- UpdateCalendar;
- end;
- end;
- { TCalendarLabel }procedure TCalendarLabel.SetSource(Value: TStringsCalendar);begin
- { set FCalendarSource := Value }
- FCalendarSource := Value;
- { if successful hook HookEvent }
- if (FCalendarSource <> nil) then
- FCalendarSource.HookEvent := DateChange;
- { update label }
- UpdateLabel;
- end;
-
- procedure TCalendarLabel.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- { If the connected TBaseCalendar has been deleted, make the connection nil }
- if (Operation = opRemove) and (AComponent = FCalendarSource) then
- FCalendarSource := nil;
- end;
-
- procedure TCalendarLabel.Loaded;
- begin
- inherited loaded;
- { after loaded update label }
- UpdateLabel;
- end;
-
- procedure TCalendarLabel.DateChange(Sender: TObject);
- begin
- { on HookEvent being triggered update label }
- UpdateLabel;
- end;
-
- procedure TCalendarLabel.UpdateLabel;
- begin
- { change caption to new date }
- if (FCalendarSource <> nil) then
- Caption := FormatDateTime('mmmm dd, yyyy', FCalendarSource.CalendarDate);
- end;
- end.